package github.sf.fw.tools.serializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.TextNode;

import java.io.IOException;

/**
 * ConstraintDesc使用Jackson的反序列化类
 * example:
 * <pre>
 *         String s = Jsons.Jackson.toPrettyJson(new ImplementMarkerImpl());
 *         System.out.println(s);
 *         ObjectMapper objectMapper = new ObjectMapper();
 *         SimpleModule simpleModule = new SimpleModule();
 *         simpleModule.addDeserializer(ConstraintDesc.class, new ImplJacksonDeserializer());
 *         objectMapper.registerModule(simpleModule);
 *         ImplementMarker impl = objectMapper.readValue(s, ImplementMarker.class);
 *         System.out.println(impl.getImplType());
 * </pre>
 */
public class ImplJacksonDeserializer extends JsonDeserializer<ImplementMarker> {
    private final ImplContainer implContainer;

    public ImplJacksonDeserializer() {
        this.implContainer = ImplContainer.getInstance();
    }

    @Override
    public ImplementMarker deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        //解析Json
        TreeNode treeNode = p.getCodec().readTree(p);
        String constraintType = null;
        TreeNode constraintTypeNode = treeNode.get(ImplementMarker.ImplTypeProperty);
        if (constraintTypeNode.isValueNode()) {
            if (constraintTypeNode instanceof TextNode) {
                constraintType = ((TextNode) constraintTypeNode).textValue();
            }
        }

        Class<? extends ImplementMarker> aClass = implContainer.resolveClass(constraintType);
        try (JsonParser traverse = treeNode.traverse(p.getCodec())) {
            return innerDeserialize(traverse, aClass);
        }
    }

    private ImplementMarker innerDeserialize(JsonParser p, Class<? extends ImplementMarker> clazz) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
//        objectMapper.configure(JsonParser.Feature.IGNORE_UNDEFINED,true);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        try {
            return objectMapper.readValue(p, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
